<?xml version="1.0" encoding="UTF-8"?>
<!--
   - multiref.xsl
   - Build utility for reusing xspec for multiple tag documents
   -
   - Copyright (c) 2011 Erik Hennum. All Rights Reserved.
   -
   - Licensed under the Apache License, Version 2.0 (the "License");
   - you may not use this file except in compliance with the License.
   - You may obtain a copy of the License at
   -
   - http://www.apache.org/licenses/LICENSE-2.0
   -
   - Unless required by applicable law or agreed to in writing, software
   - distributed under the License is distributed on an "AS IS" BASIS,
   - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   - See the License for the specific language governing permissions and
   - limitations under the License.
   -
   - The use of the Apache License does not indicate that this work is
   - associated with the Apache Software Foundation.
   -
  -->
<xsl:stylesheet version="2.0"
    xmlns:xsl    = "http://www.w3.org/1999/XSL/Transform"
    xmlns:fn     = "http://www.w3.org/2005/xpath-functions"
    xmlns:xs     = "http://www.w3.org/2001/XMLSchema"
    xmlns:xpc    = "http://www.jenitennison.com/xslt/xspec"
    xmlns:xst    = "http://code.google.com/p/xstag/ns/2011/"
    xmlns:xstest = "http://code.google.com/p/xstag/ns/2011/test"
    >

<xsl:param name="destdir" as="xs:string"/>
<xsl:param name="doclist" as="xs:string"/>
<xsl:param name="docmain" as="xs:string"/>

<xsl:variable name="outdir" as="xs:string">
  <xsl:choose>
  <xsl:when test="fn:contains($destdir,'\')">
    <xsl:choose>
    <xsl:when test="fn:matches($destdir,'^[A-Z]:')">
      <xsl:value-of select="fn:concat('file://',
              '/',fn:translate($destdir,'\','/')
              )"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="fn:concat('file://',
              fn:translate($destdir,'\','/')
              )"/>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="fn:concat('file://',$destdir)"/>
  </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:template match="/">
  <xsl:variable name="doc" as="document-node()" select="."/>

  <xsl:variable name="isXSpec"    as="xs:boolean"
      select="fn:exists(xpc:description)"/>
  <xsl:variable name="isTagDoc"   as="xs:boolean"
      select="fn:not($isXSpec) and fn:exists(doc/xst:import)"/>
  <xsl:variable name="isExpected" as="xs:boolean"
      select="fn:not($isXSpec) and fn:not($isTagDoc) and fn:exists(*/@xstest:variants)"/>

  <xsl:if test="fn:not($isXSpec or $isTagDoc or $isExpected)">
    <xsl:message terminate="yes">
      <xsl:text>Can only process xspec or tag doc or expected: </xsl:text>
      <xsl:value-of select="fn:name(*)"/>
    </xsl:message>
  </xsl:if>

  <xsl:variable name="copysuffix" as="xs:string">
    <xsl:choose>
    <xsl:when test="$isXSpec">
      <xsl:text>.xspec</xsl:text>
    </xsl:when>
    <xsl:when test="$isTagDoc">
      <xsl:text>Doc.xml</xsl:text>
    </xsl:when>
    <xsl:when test="$isExpected">
      <xsl:text>.xml</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:message terminate="yes"><xsl:text>Unknown copysuffix</xsl:text></xsl:message>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="list" as="xs:string">
    <xsl:choose>
    <xsl:when test="$isXSpec">
      <xsl:value-of select="xpc:description/@stylesheet"/>
    </xsl:when>
    <xsl:when test="$isTagDoc">
      <xsl:value-of select="$doclist"/>
    </xsl:when>
    <xsl:when test="$isExpected">
      <xsl:value-of select="*/@xstest:variants"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:message terminate="yes"><xsl:text>Unknown list</xsl:text></xsl:message>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="alternatives" as="xs:string*"
      select="fn:tokenize(fn:normalize-space($list), '[\s,]+')"/>

  <xsl:variable name="main" as="xs:string">
    <xsl:choose>
    <xsl:when test="$isXSpec">
      <xsl:value-of select="$alternatives[1]"/>
    </xsl:when>
    <xsl:when test="$isTagDoc">
      <xsl:value-of select="$docmain"/>
    </xsl:when>
    <xsl:when test="$isExpected">
      <xsl:value-of select="$alternatives[1]"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:message terminate="yes"><xsl:text>Unknown main</xsl:text></xsl:message>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:for-each select="$alternatives">
    <xsl:variable name="alternative" as="xs:string" select="."/>

    <xsl:variable name="rootname" as="xs:string">
      <xsl:choose>
      <xsl:when test="$isXSpec">
        <xsl:value-of select="fn:replace($alternative, '\.[^.]+$', '')"/>
      </xsl:when>
      <xsl:when test="$isTagDoc">
        <xsl:value-of select="fn:replace($alternative, 'Lib\.xstag$', '')"/>
      </xsl:when>
      <xsl:when test="$isExpected">
        <xsl:value-of select="$alternative"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message terminate="yes"><xsl:text>Unknown rootname</xsl:text></xsl:message>
      </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="refname" as="xs:string">
      <xsl:choose>
      <xsl:when test="$isXSpec">
        <xsl:value-of select="fn:concat($rootname, '.xsl')"/>
      </xsl:when>
      <xsl:when test="$isTagDoc">
        <xsl:value-of select="$alternative"/>
      </xsl:when>
      <xsl:when test="$isExpected">
        <xsl:value-of select="fn:concat($rootname, '.xml')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message terminate="yes"><xsl:text>Unknown refname</xsl:text></xsl:message>
      </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:choose>
    <xsl:when test="$alternative eq $main">

      <xsl:apply-templates select="$doc/node()">
        <xsl:with-param name="refname" select="$refname"/>
      </xsl:apply-templates>

    </xsl:when>
    <xsl:otherwise>

      <xsl:result-document
          href="{fn:concat($outdir, '/', $rootname, $copysuffix)}"
          method="xml"
          validation="strip"
          omit-xml-declaration="no">

        <xsl:apply-templates select="$doc/node()">
          <xsl:with-param name="refname" select="$refname"/>
        </xsl:apply-templates>

      </xsl:result-document>

    </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
</xsl:template>

<xsl:template match="/xpc:description">
  <xsl:param name="refname"/>
  <xsl:copy>
    <xsl:copy-of select="@* except @stylesheet"/>
    <xsl:attribute name="stylesheet" select="$refname"/>
    <xsl:copy-of select="node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="/*">
  <xsl:param name="refname"/>
  <xsl:copy>
    <xsl:copy-of select="@* except @xstest:variants"/>
    <xsl:apply-templates select="node()">
      <xsl:with-param name="refname" select="$refname"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="/doc/xst:import">
  <xsl:param name="refname"/>
  <xsl:copy>
    <xsl:copy-of select="@* except @href"/>
    <xsl:attribute name="href" select="$refname"/>
    <xsl:copy-of select="node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="node()">
  <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>